package com.greensam.pixelengine.service.impl;

import com.greensam.pixelengine.pojo.base.PaginationResponse;
import com.greensam.pixelengine.pojo.emuns.SpaceTypeEnum;
import com.greensam.pixelengine.pojo.entity.QSpacePo;
import com.greensam.pixelengine.pojo.entity.SpacePo;
import com.greensam.pixelengine.pojo.query.SpacePageQuery;
import com.greensam.pixelengine.pojo.query.SpaceRankListQuery;
import com.greensam.pixelengine.repository.SpaceRepository;
import com.greensam.pixelengine.service.SpaceDataService;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author Ma Chengrui
 * @since 2025/8/2 14:23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SpaceDataServiceImpl implements SpaceDataService {

    private final JPAQueryFactory jpaQueryFactory;
    private final SpaceRepository spaceRepository;

    @Override
    public PaginationResponse<SpacePo> pageSpace(SpacePageQuery pageQuery) {
        QSpacePo s = QSpacePo.spacePo;

        BooleanBuilder condition = new BooleanBuilder();
        condition.and(s.delete.eq(Boolean.FALSE));
        if (Objects.nonNull(pageQuery.getUserId())) {
            condition.and(s.createBy.eq(pageQuery.getUserId()));
        }
        if (StringUtils.isNotBlank(pageQuery.getName())) {
            condition.and(s.name.eq(pageQuery.getName()));
        }
        if (Objects.nonNull(pageQuery.getLevel())) {
            condition.and(s.level.eq(pageQuery.getLevel()));
        }

        Long totalCount = jpaQueryFactory.select(s.id.countDistinct())
                .from(s)
                .where(condition)
                .fetchOne();
        if (Objects.isNull(totalCount) || totalCount == 0) {
            return PaginationResponse.empty(pageQuery.getPageSize(), pageQuery.getPageNum());
        }

        List<SpacePo> result = jpaQueryFactory.selectFrom(s)
                .where(condition)
                .orderBy(s.updateTime.desc())
                .offset(pageQuery.offset())
                .limit(pageQuery.getPageSize())
                .fetch();
        return PaginationResponse.page(result, totalCount, pageQuery.getPageSize(), pageQuery.getPageNum());
    }

    @Override
    public Optional<SpacePo> getSpaceById(Long id) {
        if (Objects.isNull(id)) {
            return Optional.empty();
        }
        QSpacePo s = QSpacePo.spacePo;
        return Optional.ofNullable(jpaQueryFactory.selectFrom(s)
                .where(s.id.eq(id))
                .where(s.delete.eq(Boolean.FALSE))
                .fetchOne());
    }

    @Override
    public Optional<SpacePo> getSpaceByUserId(Long userId, SpaceTypeEnum spaceType) {
        QSpacePo s = QSpacePo.spacePo;
        BooleanBuilder condition = new BooleanBuilder();
        condition.and(s.delete.eq(Boolean.FALSE));
        if (Objects.nonNull(userId)) {
            condition.and(s.createBy.eq(userId));
        }
        if (Objects.nonNull(spaceType)) {
            condition.and(s.type.eq(spaceType));
        }
        return Optional.ofNullable(jpaQueryFactory.selectFrom(s)
                .where(condition)
                .fetchOne());
    }

    @Override
    public SpacePo save(SpacePo spacePo) {
        if (Objects.isNull(spacePo)) {
            return null;
        }
        return spaceRepository.save(spacePo);
    }

    @Override
    public List<SpacePo> listSpace() {
        QSpacePo s = QSpacePo.spacePo;
        return jpaQueryFactory.selectFrom(s)
                .where(s.delete.eq(Boolean.FALSE))
                .fetch();
    }

    @Override
    public List<SpacePo> listSpaceRank(SpaceRankListQuery query) {
        QSpacePo s = QSpacePo.spacePo;
        return jpaQueryFactory.selectFrom(s)
                .where(s.delete.eq(Boolean.FALSE))
                .orderBy(s.totalSize.desc())
                .limit(query.getTopN())
                .fetch();
    }

    @Override
    public List<SpacePo> listSpaceByIds(Collection<Long> spaceIds) {
        if (spaceIds.isEmpty()) {
            return Collections.emptyList();
        }
        QSpacePo s = QSpacePo.spacePo;
        return jpaQueryFactory.selectFrom(s)
                .where(s.id.in(spaceIds)
                        .and(s.delete.eq(Boolean.FALSE)))
                .fetch();
    }

}
